package com.cjack.frenchexcel.service;

import com.cjack.frenchexcel.config.AjaxResult;
import com.cjack.frenchexcel.dao.EasyEuroDao;
import com.cjack.frenchexcel.model.AdminUserModel;
import com.cjack.frenchexcel.model.RechargeRecordModel;
import com.cjack.frenchexcel.request.easyeuro.NotifyPayResultRequest;
import com.cjack.frenchexcel.response.easyeuro.GetAlipayQrCodeResponse;
import com.cjack.frenchexcel.response.easyeuro.QueryPaymentOrderResponse;
import com.cjack.frenchexcel.table.AdminUserTable;
import com.cjack.frenchexcel.table.EasyEuroTable;
import com.cjack.frenchexcel.table.RechargeRecordTable;
import com.cjack.frenchexcel.util.*;
import net.sf.json.JSONObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class EasyEuroService {
    private final static Logger LOG = LogManager.getLogger( EasyEuroService.class);

    @Autowired
    private RechargeRecordService rechargeRecordService;
    @Autowired
    EasyEuroDao easyEuroDao;
    @Autowired
    UserAdminService userAdminService;

    @Value( "${easyeuro.server}")
    private String server;
    @Value( "${easyeuro.key}")
    private String key;
    @Value( "${easyeuro.merchant.account}")
    private String merchantAccount;
    @Value( "${easyeuro.merchant.name}")
    private String merchantName;
    @Value( "${easyeuro.merchant.ip}")
    private String merchantIp;
    @Value( "${easyeuro.merchant.notifyUrl}")
    private String notifyUrl;

    public void notifyPayRes( String requestXml) throws Exception {
        JSONObject requestJson = XmlUtil.xmlToJson( requestXml);
        NotifyPayResultRequest request = (NotifyPayResultRequest)JSONObject.toBean( requestJson, NotifyPayResultRequest.class);
        if( "0".equals( request.getStatus()) && "0".equals( request.getResult_code())){
            //调用 EasyEuro确认本次支付是否真正完成
            String orderNo = request.getOut_trade_no();
            if( this.checkPayResult( orderNo)){
                //判断这个订单是否已经入库，防止这个成功的消息被推送两次，创造两条数据
                RechargeRecordTable rechargeRecordTable = rechargeRecordService.queryByOrderNo( orderNo);
                if( rechargeRecordTable != null){
                    LOG.info( "订单号[" + orderNo + "]对应的订单支付成功的消息已经收到，不需要再次处理");
                    return;
                }
                //获取支付二维码送过去的附加参数里面的信息
                String attach = request.getAttach();
                if( StringUtils.isEmpty( attach)){
                    LOG.error( "attach为空，不处理");
                    return;
                }
                Long adminUserId = Long.valueOf( attach.split( "_")[0]);
                String merchant_total_fee = attach.split( "_")[1];

                //创建一条充值记录
                EasyEuroTable model = new EasyEuroTable();
                model.setDealTime( DateFormatUtil.format( new Date(), DateFormatUtil.DATE_RULE_3));//交易时间-中国
                model.setDealTimeFrench( DateFormatUtil.chinaTimeToFrench( model.getDealTime()));//交易时间-法国
                model.setMerchantOrderNo( orderNo);//商户订单号
                model.setPlatformOrderNo( request.getTransaction_id());//平台订单号
                model.setThirdPartyOrderNo( request.getOut_transaction_id());//第三方订单号
                model.setMerchantName( merchantName);//商户名称
                model.setMerchantNumber( merchantAccount);//商户号
                model.setPayType( "Alipay-JS Pay");//支付类型
                model.setDealStatus( "Successful");//交易状态
                model.setRefundMoney( "0.00");//退款金额
                double payMoney = Double.valueOf( request.getTotal_fee()) / 100;
                model.setPayMoney( payMoney + "");//支付金额
                model.setPayCurrencyType( request.getFee_type());//支付币种
                model.setExchangeRate( "----");//汇率 --暂时无值
                model.setMerchantOrderAmount( merchant_total_fee);//商户订单总额
                model.setMerchantCurrencyType( "EUR");//商户币种
                model.setTerminalNumber( "QR_CODE");//终端设备号
                model.setMemo( "");//备注
                model.setMoneyStatus( "2");//设置到账状态为已经到账
                //EasyEuro自动对应收款方式R01
                model.setRechargeTypeCode( "R01");
                model.setImportUserId( adminUserId);
                model.setCreateTime( new Date());
                model.setUpdateTime( new Date());
                this.save( model);
            }else{
                throw new Exception( "调用EasyEuro查询订单状态为未支付");
            }
        }
    }

    private void save( EasyEuroTable model){
        easyEuroDao.save( model);
    }


    /**
     * 后台调用此接口，获取本次支付的二维码
     * @return
     */
    public AjaxResult getRechargeQrCode( Long adminUserId, double totalFee) throws Exception {
        String orderNo = CustomerStringUtil.getOrderNo( adminUserId);
        Long totalFeeL = (long)(totalFee * 100);
        SortedMap< String, String> map = new TreeMap<>();
        map.put( "service", "pay.alipay.native.intl");
        map.put( "mch_id", merchantAccount);
        map.put( "out_trade_no", orderNo);
        map.put( "body", "service");
        map.put( "total_fee", String.valueOf( totalFeeL));
        map.put( "mch_create_ip", merchantIp);
        map.put( "notify_url", notifyUrl);
        map.put( "nonce_str", CustomerStringUtil.randomStr( 12));
        String attach = adminUserId + "_" + totalFee;
        map.put( "attach", attach);
        map.put( "sign", getSign( map));

        String requestXml = XmlUtil.mapToXlm( map);
        LOG.info( "getRechargeQrCode-requestXml-------------------------------" + requestXml);
        String responseXml = HttpClientUtil.doPost( server, null, requestXml);
        LOG.info( "getRechargeQrCode-responseXml-------------------------------" + responseXml);
        JSONObject responseJson = XmlUtil.xmlToJson( responseXml);
        GetAlipayQrCodeResponse response = (GetAlipayQrCodeResponse)JSONObject.toBean( responseJson, GetAlipayQrCodeResponse.class);
        //返回给页面的内容
        JSONObject result = new JSONObject();
        result.put( "orderNo", orderNo);
        AdminUserTable user = userAdminService.get( adminUserId);
        result.put( "nom", user.getNom());
        result.put( "prenom", user.getPrenom());
        //判断获取二维码是否成功
        if( "0".equals( response.getStatus()) && "0".equals( response.getResult_code())){
            result.put( "codeImgUrl", response.getCode_img_url());
        }else{
            LOG.error( response.getMessage());
            return AjaxResult.ERROR();
        }
        return AjaxResult.SUCCESS( result);
    }

    public boolean checkPayResult( String orderNo) throws Exception{
        QueryPaymentOrderResponse response = queryPayResult( orderNo);
        if( response != null && "0".equals( response.getStatus()) && "0".equals( response.getResult_code()) && "SUCCESS".equals( response.getTrade_state())){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 调用EasyEuro查询本次支付的信息
     * @return
     */
    private QueryPaymentOrderResponse queryPayResult( String orderNo) throws Exception {
        SortedMap< String, String> map = new TreeMap<>();
        map.put( "service", "unified.trade.query");
        map.put( "mch_id", merchantAccount);
        map.put( "out_trade_no", orderNo);
        map.put( "nonce_str", CustomerStringUtil.randomStr( 12));
        map.put( "sign", getSign( map));

        String requestXml = XmlUtil.mapToXlm( map);
        LOG.info( "queryPayResult-requestXml-------------------------------" + requestXml);
        String responseXml = HttpClientUtil.doPost( server, null, requestXml);
        LOG.info( "queryPayResult-responseXml-------------------------------" + responseXml);
        JSONObject responseJson = XmlUtil.xmlToJson( responseXml);
        QueryPaymentOrderResponse response = (QueryPaymentOrderResponse)JSONObject.toBean( responseJson, QueryPaymentOrderResponse.class);
        return response;
    }

    /**
     * 查询数据库里面，订单号对应的订单是否已经支付
     * @param orderNo
     * @return
     */
    public RechargeRecordModel queryOrderStatus( String orderNo){
        RechargeRecordTable table = rechargeRecordService.queryByOrderNo( orderNo);
        if( table != null){
            return ModelUtils.copySignModel( table, RechargeRecordModel.class);
        }else{
            return null;
        }
    }

    /**
     * 获取接口参数签名
     * @param params
     * @return
     */
    private String getSign( SortedMap< String, String> params){
        StringBuilder sb = new StringBuilder();
        for ( Map.Entry< String, String> entry : params.entrySet()) {
            if( !StringUtils.isEmpty( entry.getValue())){
                sb.append( entry.getKey()).append( "=").append( entry.getValue()).append( "&");
            }
        }
        sb.append( "key=").append( key);
        String sign = Md5Util.stringToMD5( sb.toString()).toUpperCase();
        return sign;
    }

    public static void main(String[] args) {
        String str = "body=iPhone&charset=UTF-8&device_info=SN12345678&mch_create_ip=103.218.216.123&mc" +
                "h_id=157590000059&nonce_str=ibuaiVcKdpRxkhJA&notify_url=http://www.baidu.com&op_user" +
                "_id=10001&out_trade_no=Q3NL0000442503084402&product_id=123456789&service=pay.alipa" +
                "y.native.intl&sign_type=MD5&time_expire=20180526212310&time_start=20180526202310&tot" +
                "al_fee=10&version=2.0&key=c43a467098af250171cd787e56d03978";
        String sign = Md5Util.stringToMD5( str).toUpperCase();
        System.out.println( sign);

        double l1 = 1.55;
        double l2 = 0.2;
        System.out.println( l1 / l2);

        double d3 = 1;
        System.out.println( d3 / 100);
    }
}
